<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>sheep-sheep</title>
  <style>
    body {
      margin: 0;
      padding: 0;
    }
    #main {
      border:1px solid #ccc;
      position: relative;
      box-sizing: border-box;
    }
    .item {
      text-align: center;
      border-radius: 2px;
      box-sizing: border-box;
      padding: 5px;
      color: antiquewhite;
      cursor: pointer;
      user-select: none;
      transition: all 0.3s;
    }

    #moveList {
      border: 1px solid #ccc;
      position: relative;
      margin-top: 20px;
      margin-left: 20px;
    }
  </style>
</head>
<body>
  <div id="main"></div>
  <div id="moveList"></div>
  <script>
    const SIZE = 30
    const COLS = 10
    const ROWS = 10
    // 几个一样的图形会消除
    const MOVENUMS = 3
    // 图形层数
    const LAYERS = 6
    // 一层放置几组图片
    const TOTAL_GROUP_NUMS = 2
    // 消除行最多放置几个图片
    const MOVELISTNUMS = 8

    const cards = [
      {name: "鼠", typeId: 1, bgcolor: "pink"},
      {name: "牛", typeId: 2, bgcolor: "red"},
      {name: "虎", typeId: 3, bgcolor: "#41a266"},
      {name: "兔", typeId: 4, bgcolor: "green"},
      {name: "龙", typeId: 5, bgcolor: "rgb(252, 127, 31)"},
      {name: "蛇", typeId: 6, bgcolor: "skyblue"}
    ]

    // 存放上方主视图图片
    let itemList = []
    // 存放下方消除列表图片
    let moveList = []

    const init = () => {
      // 生成背景
      const main = document.querySelector("#main")
      main.style = `height: ${COLS * SIZE + SIZE/2}px;width: ${ROWS * SIZE + SIZE/2}px;padding: 0 ${SIZE/2}px 0`

      const moveListEl = document.querySelector("#moveList")
      moveListEl.style = `height: ${SIZE}px;width: ${MOVELISTNUMS * SIZE}px;`
    
      const cardsList = getRandomCardsList()

      initCards(cardsList)
    }

    //  获取随机排列卡片数组
    const getRandomCardsList = () => {
      let cardsList = []
      for (let i = 0; i < LAYERS * TOTAL_GROUP_NUMS; i++) {
        cardsList.push(cards.slice())
      }
      cardsList = cardsList.flat().sort(v => Math.random() - 0.5)
      
      return cardsList
    }

    // 将卡片数组进行初始化显示
    const initCards = (cardsList) => {
      const itemStrList = []
      for (let i = 0; i < LAYERS; i++) {
        layerNums = 0
        for (let j = 0; j < COLS; j++) {
          for (let k = 0; k < ROWS; k++) {
            if (layerNums < cards.length * TOTAL_GROUP_NUMS && Math.random() > 0.85) {
              const item = cardsList.pop()
              // 双数层不偏移/单数层偏移
              let py = i % 2 === 0 ? 0 : SIZE/2
              // 最顶层高亮,其他设置灰度
              let grayscale = i === LAYERS-1 ? 0 : 99

              itemStrList.push(`<div typeid="${item.typeId}" class="item" id="m${i}-${j}-${k}" style="width:${SIZE}px;height:${SIZE}px;background:${item.bgcolor};position:absolute;left:${(j) * SIZE + py}px;top:${(k) * SIZE + py}px;filter:grayscale(${grayscale}%)">${item.name}</div>`)
              layerNums += 1
            }
          }
        }
      }
    
      main.innerHTML = itemStrList.join('')
      itemList = Array.from(document.getElementsByClassName("item"))
      // 添加点击事件
      addClickEvent()
      showTop()
    }

    // 添加点击事件
    addClickEvent = () => {
      for (let i = 0; i < itemList.length; i++) {
        if (itemList[i].onClick) {
          break
        }
        itemList[i].addEventListener("click", (el) => {clickHandler(el, i)})
      }
    }

    // 点击事件处理函数
    clickHandler = (el, i) => {
      // console.log("ding");
      if (isTop(el.target)) {
        itemList = itemList.filter(item => {
          return item !== el.target
        })
        // console.log(itemList.length);
        moveList.push(el.target)
        // console.log(moveList.length);
        renderMoveList(el.target)

        showTop()
      } else {
        console.log("nothing");
        return
      }
    }

    // 判断图片是否处于顶层
    isTop = (el) => {
      const idList = el.id.slice(1,).split("-")
      const layers = parseInt(idList[0])
      const cols = parseInt(idList[1])
      const rows = parseInt(idList[2])

      if (layers == LAYERS-1) {
        return true
      }

      if (layers % 2 === 0) {
        // console.log(layers);
        let searchIdList = []
        for (let i = layers+1; i < LAYERS; i += 1) {
          if ((i - layers) % 2 !== 0) {
            searchIdList = searchIdList.concat([
              `#m${i}-${cols-1}-${rows-1}`,
              `#m${i}-${cols-1}-${rows}`,
              `#m${i}-${cols}-${rows-1}`,
              `#m${i}-${cols}-${rows}`,
            ])
          } else {
            searchIdList = searchIdList.concat([
              `#m${i}-${cols}-${rows}`
            ])
          }
        }

        for (let searchId of searchIdList) {
          const elSearch = itemList.filter(el => {
            return el.id === searchId.slice(1,)
          })
          if (elSearch.length) {
            // console.log(el, elSearch);
            return false
          }
        }
        return true
      }

      if (layers % 2 !== 0) {
        let searchIdList = []
        for (let i = layers+1; i < LAYERS; i += 1) {
          if ((i - layers) % 2 !== 0) {
            searchIdList = searchIdList.concat([
              `#m${i}-${cols+1}-${rows+1}`,
              `#m${i}-${cols+1}-${rows}`,
              `#m${i}-${cols}-${rows+1}`,
              `#m${i}-${cols}-${rows}`,
            ])
          } else {
            searchIdList = searchIdList.concat([
              `#m${i}-${cols}-${rows}`
            ])
          }
        }

        for (let searchId of searchIdList) {
          const elSearch = itemList.filter(el => {
            return el.id === searchId.slice(1,)
          })
          if (elSearch.length) {
            return false
          }
        }
        return true
      }

      return false
    }

    // 获取元素上层的所有元素列表
    getTopEl = (el) => {
      const idList = el.id.slice(1,).split("-")
      const layers = parseInt(idList[0])
      const cols = parseInt(idList[1])
      const rows = parseInt(idList[2])

      let searchIdList = []

      // 顶层元素
      if (layers == LAYERS-1) {
        return searchIdList
      }

      // 双数层
      if (layers % 2 === 0) {       
        for (let i = layers+1; i < LAYERS; i += 1) {
          if ((i - layers) % 2 !== 0) {
            searchIdList = searchIdList.concat([
              `#m${i}-${cols-1}-${rows-1}`,
              `#m${i}-${cols-1}-${rows}`,
              `#m${i}-${cols}-${rows-1}`,
              `#m${i}-${cols}-${rows}`,
            ])
          } else {
            searchIdList = searchIdList.concat([
              `#m${i}-${cols}-${rows}`
            ])
          }
        }
      }

      // 单数层
      if (layers % 2 !== 0) {
        let searchIdList = []
        for (let i = layers+1; i < LAYERS; i += 1) {
          if ((i - layers) % 2 !== 0) {
            searchIdList = searchIdList.concat([
              `#m${i}-${cols+1}-${rows+1}`,
              `#m${i}-${cols+1}-${rows}`,
              `#m${i}-${cols}-${rows+1}`,
              `#m${i}-${cols}-${rows}`,
            ])
          } else {
            searchIdList = searchIdList.concat([
              `#m${i}-${cols}-${rows}`
            ])
          }
        }
      }

      return searchIdList
    }

    // 重新渲染移除列表
    renderMoveList = (el) => {
      sameEls = moveList.filter(item => {
        return item.getAttribute("typeid") === el.getAttribute("typeid")
      })

      // 当相同元素达到三个，去除moveList中所有该类图片
      if (sameEls.length === MOVENUMS) {
        // console.log(sameEls);
        sameEls.forEach(el => {
          el.style.transform = `scale(0)`
        })
        moveList = moveList.filter(item => {
          return item.getAttribute("typeid") !== el.getAttribute("typeid")
        })
      }

      // 重新渲染
      const moveListEl = document.querySelector("#moveList")
      const moveListLeft = moveListEl.offsetLeft
      const moveListTop = moveListEl.offsetTop
      for (let id in moveList) {
        moveList[id].style.left = `${moveListLeft + id * SIZE}px`
        moveList[id].style.top = `${moveListTop}px`
      }

      if (moveList.length > MOVELISTNUMS) {
        alert('laji！')
        return
      }
    }

    showTop = () => {
      console.log("show");
      for (let el of itemList) {
        if (isTop(el)) {
          el.style.filter = `grayscale(0%)`
        } else {
          // console.log(el);
          el.style.filter = `grayscale(99%)`
        }
      }
      // addClickEvent()
    }
    
    init()

  </script>
</body>
</html>